<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件管理器</title>
    <!-- 引入Element UI CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui/lib/theme-chalk/index.css">
    <!-- 引入Font Awesome图标 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
            background-color: #f5f7fa;
            color: #303133;
            min-height: 100vh;
        }
        
        .file-manager-container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .header {
            background: white;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        
        .header h1 {
            margin: 0;
            font-size: 24px;
            color: #1f2937;
        }
        
        .breadcrumb {
            background: white;
            padding: 15px 20px;
            border-radius: 8px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            display: flex;
            align-items: center;
            flex-wrap: wrap;
        }
        
        .breadcrumb-item {
            display: flex;
            align-items: center;
            cursor: pointer;
            padding: 5px 10px;
            border-radius: 4px;
            transition: all 0.3s;
        }
        
        .breadcrumb-item:hover {
            background-color: #f5f7fa;
        }
        
        .breadcrumb-item.active {
            color: #409eff;
        }
        
        .breadcrumb-separator {
            margin: 0 10px;
            color: #c0c4cc;
        }
        
        .back-btn {
            margin-right: 20px;
        }
        
        .file-grid {
            background: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        
        .file-items {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }
        
        .file-item {
            border: 1px solid #ebeef5;
            border-radius: 8px;
            padding: 15px;
            transition: all 0.3s;
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }
        
        .file-item:hover {
            border-color: #409eff;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        }
        
        .file-icon {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100px;
            margin-bottom: 10px;
            font-size: 48px;
        }
        
        .file-icon.folder {
            color: #e6a23c;
            font-size: 80px; /* 进一步增大文件夹图标大小 */
        }
        
        .file-icon.image {
            color: #5cb87a;
        }
        
        .file-icon.file {
            color: #409eff;
        }
        
        .file-name {
            text-align: center;
            font-size: 14px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            margin-bottom: 5px;
        }
        
        .file-size {
            text-align: center;
            font-size: 12px;
            color: #909399;
        }
        
        .file-actions {
            position: absolute;
            top: 5px;
            right: 5px;
            opacity: 0;
            transition: opacity 0.3s;
        }
        
        .file-item:hover .file-actions {
            opacity: 1;
        }
        
        .action-btn {
            width: 28px;
            height: 28px;
            border-radius: 4px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-left: 5px;
            background-color: rgba(255, 255, 255, 0.9);
            border: 1px solid #dcdfe6;
            transition: all 0.3s;
        }
        
        .action-btn:hover {
            background-color: #f5f7fa;
            border-color: #c0c4cc;
        }
        
        .action-btn.delete:hover {
            background-color: #fef0f0;
            border-color: #fbc4c4;
            color: #f56c6c;
        }
        
        .action-btn.preview:hover {
            background-color: #ecf5ff;
            border-color: #b3d8ff;
            color: #409eff;
        }
        
        .action-btn.download:hover {
            background-color: #f0f9eb;
            border-color: #a0d911;
            color: #67c23a;
        }
        
        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #909399;
        }
        
        .empty-state i {
            font-size: 64px;
            margin-bottom: 20px;
            color: #c0c4cc;
        }
        
        .preview-modal .el-dialog__body {
            padding: 0;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #000;
        }
        
        .preview-modal img {
            max-width: 100%;
            max-height: 70vh;
        }
        
        @media (max-width: 768px) {
            .file-items {
                grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            }
        }
    </style>
</head>
<body>
    <div class="file-manager-container" id="app">
        <div class="header">
            <h1><i class="fa fa-folder-open"></i> 文件管理器</h1>
            <el-button type="success" icon="el-icon-plus" size="small" @click="showCreateFolderDialog">
                新建文件夹
            </el-button>
        </div>
        
        <div class="breadcrumb">
            <el-button type="primary" icon="el-icon-arrow-left" size="mini" class="back-btn" @click="navigateUp" :disabled="!canNavigateUp">
                返回上级
            </el-button>
            <div class="breadcrumb-item active" @click="navigateTo('')">
                <i class="fa fa-home"></i> 根目录
            </div>
            <template v-for="(item, index) in currentPathArray" :key="index">
                <span class="breadcrumb-separator">/</span>
                <div class="breadcrumb-item" @click="navigateTo(item.path)">
                    {{ item.name }}
                </div>
            </template>
        </div>
        
        <div class="file-grid">
            <div class="file-items" v-if="fileItems.length > 0">
                <div 
                    v-for="item in fileItems" 
                    :key="item.path"
                    class="file-item"
                    @click="handleItemClick(item)"
                >
                    <div class="file-icon" :class="getItemIconClass(item)">
                        <i :class="getItemIcon(item)"></i>
                    </div>
                    <div class="file-name">{{ item.name }}</div>
                    <!-- 只显示文件的大小，隐藏文件夹的容量大小 -->
                    <div class="file-size" v-if="!item.directory">{{ formatFileSize(item.size) }}</div>
                    <div class="file-actions">
                        <!-- 只对图片、视频、音频、PDF和文本文件显示预览按钮，隐藏文档类预览 -->
                        <button 
                            v-if="!item.directory && (isImageFile(item) || isPdfFile(item) || isTextFile(item) || ['mp4', 'mov', 'avi', 'mp3', 'wav'].includes(item.type?.toLowerCase()))" 
                            class="action-btn preview"
                            @click.stop="previewFile(item)"
                            title="预览"
                        >
                            <i class="fa fa-eye"></i>
                        </button>
                        <button 
                            v-if="!item.directory" 
                            class="action-btn download"
                            @click.stop="downloadFile(item.path)"
                            title="下载"
                        >
                            <i class="fa fa-download"></i>
                        </button>
                        <button 
                            class="action-btn delete"
                            @click.stop="deleteItem(item)"
                            title="删除"
                        >
                            <i class="fa fa-trash"></i>
                        </button>
                    </div>
                </div>
            </div>
            
            <div class="empty-state" v-else-if="!loading">
                <i class="fa fa-folder-open-o"></i>
                <p>当前目录为空</p>
            </div>
            
            <div class="empty-state" v-else>
                <i class="fa fa-spinner fa-spin"></i>
                <p>加载中...</p>
            </div>
        </div>
        
        <!-- 预览对话框 -->
        <el-dialog 
            :visible.sync="previewVisible" 
            class="preview-modal" 
            :title="previewTitle"
            width="90%"
            fullscreen
        >
            <!-- 图片预览 -->
            <div v-if="previewType === 'image'" style="background-color: #000;">
                <img :src="previewImageUrl" alt="预览图片" style="max-width: 100%; max-height: 80vh; object-fit: contain; margin: 0 auto; display: block;">
            </div>
            
            <!-- PDF预览 -->
            <div v-else-if="previewType === 'pdf'" style="background-color: #000;">
                <embed :src="previewPdfUrl" type="application/pdf" width="100%" height="80vh" />
            </div>
            
            <!-- 文本预览 -->
            <div v-else-if="previewType === 'text'" style="background-color: #000; color: #fff; padding: 20px;">
                <pre style="white-space: pre-wrap; word-wrap: break-word; max-height: 80vh; overflow-y: auto; margin: 0;">{{ previewTextContent }}</pre>
            </div>
            
            <!-- 视频预览 -->
            <div v-else-if="previewType === 'video'" style="background-color: #000; display: flex; justify-content: center; align-items: center; min-height: 80vh;">
                <video :src="previewVideoUrl" controls width="100%" height="auto">您的浏览器不支持视频标签</video>
            </div>
            
            <!-- 音频预览 -->
            <div v-else-if="previewType === 'audio'" style="background-color: #000; color: #fff; padding: 20px; display: flex; justify-content: center;">
                <audio :src="previewAudioUrl" controls>您的浏览器不支持音频标签</think>
            </div>
        </el-dialog>
        
        <!-- 新建文件夹对话框 -->
        <el-dialog 
            :visible.sync="createFolderVisible" 
            :title="'新建文件夹 - ' + (currentPath ? currentPath : '根目录')"
            width="500px"
        >
            <el-form :model="folderForm" :rules="folderRules" ref="folderForm">
                <el-form-item label="文件夹名称" prop="folderName">
                    <el-input v-model="folderForm.folderName" placeholder="请输入文件夹名称"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="cancelCreateFolder">取消</el-button>
                <el-button type="primary" @click="confirmCreateFolder">确定</el-button>
            </div>
        </el-dialog>
    </div>
    
    <!-- 引入Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
    <!-- 引入Element UI JS -->
    <script src="https://cdn.jsdelivr.net/npm/element-ui/lib/index.js"></script>
    
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    fileItems: [],
                    loading: false,
                    currentPath: '',
                    previewVisible: false,
                    previewUrl: '',
                    previewTitle: '',
                    previewType: 'image',
                    previewImageUrl: '',
                    previewPdfUrl: '',
                    previewTextContent: '',
                    previewVideoUrl: '',
                    previewAudioUrl: '',
                    // 新建文件夹相关
                    createFolderVisible: false,
                    folderForm: {
                        folderName: ''
                    },
                    folderRules: {
                        folderName: [
                            { required: true, message: '请输入文件夹名称', trigger: 'blur' },
                            { pattern: /^[^/\\:*?"<>|]+$/, message: '文件夹名称不能包含特殊字符 /\\:*?"<>|', trigger: 'blur' },
                            { max: 100, message: '文件夹名称不能超过100个字符', trigger: 'blur' }
                        ]
                    }
                };
            },
            computed: {
                canNavigateUp() {
                    return this.currentPath !== '';
                },
                currentPathArray() {
                    if (!this.currentPath) return [];
                    
                    const pathParts = this.currentPath.split('/').filter(part => part);
                    const result = [];
                    let currentPath = '';
                    
                    pathParts.forEach(part => {
                        currentPath += (currentPath ? '/' : '') + part;
                        result.push({
                            name: part,
                            path: currentPath
                        });
                    });
                    
                    return result;
                }
            },
            mounted() {
                this.loadFiles();
            },
            methods: {
                // 获取文件列表
                async fetchFiles(path) {
                    try {
                        const response = await fetch(`/upload/list/items?path=${encodeURIComponent(path || '')}`);
                        if (!response.ok) {
                            throw new Error(`网络响应错误: ${response.status}`);
                        }
                        const data = await response.json();
                        return data;
                    } catch (error) {
                        console.error('获取文件列表失败:', error);
                        throw error;
                    }
                },
                
                // 加载文件列表
                loadFiles() {
                    this.loading = true;
                    
                    this.fetchFiles(this.currentPath)
                        .then(data => {
                            this.fileItems = data;
                            console.log('加载文件列表成功:', data);
                        })
                        .catch(error => {
                            this.$message.error('加载文件失败，请稍后重试');
                        })
                        .finally(() => {
                            this.loading = false;
                        });
                },
                
                // 处理文件或文件夹点击
                handleItemClick(item) {
                    if (item.directory) {
                        // 点击文件夹，导航到子目录
                        this.navigateTo(item.path);
                    }
                },
                
                // 导航到指定路径
                navigateTo(path) {
                    this.currentPath = path;
                    this.loadFiles();
                },
                
                // 返回上级目录
                navigateUp() {
                    if (this.currentPath) {
                        const lastSlashIndex = this.currentPath.lastIndexOf('/');
                        if (lastSlashIndex > 0) {
                            this.currentPath = this.currentPath.substring(0, lastSlashIndex);
                        } else if (lastSlashIndex === 0) {
                            // 如果路径以/开头，返回根目录
                            this.currentPath = '';
                        } else {
                            this.currentPath = '';
                        }
                        this.loadFiles();
                    }
                },
                
                // 获取项目图标类
                getItemIconClass(item) {
                    if (item.directory) {
                        return 'folder';
                    } else if (this.isImageFile(item)) {
                        return 'image';
                    } else {
                        return 'file';
                    }
                },
                
                // 获取项目图标
                getItemIcon(item) {
                    if (item.directory) {
                        return 'fa fa-folder';
                    } else if (this.isImageFile(item)) {
                        return 'fa fa-file-image-o';
                    } else if (this.isPdfFile(item)) {
                        return 'fa fa-file-pdf-o';
                    } else if (this.isWordFile(item)) {
                        return 'fa fa-file-word-o';
                    } else if (this.isExcelFile(item)) {
                        return 'fa fa-file-excel-o';
                    } else if (this.isTextFile(item)) {
                        return 'fa fa-file-text-o';
                    } else {
                        return 'fa fa-file-o';
                    }
                },
                
                // 判断是否为图片文件
                isImageFile(item) {
                    const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
                    return imageTypes.includes(item.type?.toLowerCase());
                },
                
                // 判断是否为PDF文件
                isPdfFile(item) {
                    return item.type?.toLowerCase() === 'pdf';
                },
                
                // 判断是否为Word文件
                isWordFile(item) {
                    const wordTypes = ['doc', 'docx'];
                    return wordTypes.includes(item.type?.toLowerCase());
                },
                
                // 判断是否为Excel文件
                isExcelFile(item) {
                    const excelTypes = ['xls', 'xlsx'];
                    return excelTypes.includes(item.type?.toLowerCase());
                },
                
                // 判断是否为文本文件
                isTextFile(item) {
                    const textTypes = ['txt', 'log', 'md', 'json', 'xml', 'html', 'css', 'js'];
                    return textTypes.includes(item.type?.toLowerCase());
                },
                
                // 格式化文件大小
                formatFileSize(size) {
                    if (size === 0) return '0 B';
                    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
                    let i = 0;
                    let currentSize = size;
                    while (currentSize >= 1024 && i < units.length - 1) {
                        currentSize /= 1024;
                        i++;
                    }
                    return currentSize.toFixed(2) + ' ' + units[i];
                },
                
                // 获取文件URL（用于预览）
                getFileUrl(filePath) {
                    return `/upload/download?path=${encodeURIComponent(filePath)}`;
                },
                
                // 预览文件
                previewFile(item) {
                    const fileUrl = this.getFileUrl(item.path);
                    
                    if (this.isImageFile(item)) {
                        this.previewType = 'image';
                        this.previewImageUrl = fileUrl;
                        this.previewTitle = item.name;
                        this.previewVisible = true;
                    } else if (item.type?.toLowerCase() === 'pdf') {
                        this.previewType = 'pdf';
                        this.previewPdfUrl = fileUrl;
                        this.previewTitle = item.name;
                        this.previewVisible = true;
                    } else if (['doc', 'docx', 'txt', 'text'].includes(item.type?.toLowerCase())) {
                        this.loadTextPreview(item.path, item.name);
                    } else if (['mp4', 'mov', 'avi'].includes(item.type?.toLowerCase())) {
                        this.previewType = 'video';
                        this.previewVideoUrl = fileUrl;
                        this.previewTitle = item.name;
                        this.previewVisible = true;
                    } else if (['mp3', 'wav'].includes(item.type?.toLowerCase())) {
                        this.previewType = 'audio';
                        this.previewAudioUrl = fileUrl;
                        this.previewTitle = item.name;
                        this.previewVisible = true;
                    } else {
                        // 对于不支持预览的文件类型，提供下载选项
                        this.$confirm(`该文件类型(${item.type})不支持在线预览，是否下载？`, '提示', {
                            confirmButtonText: '下载',
                            cancelButtonText: '取消',
                            type: 'info'
                        }).then(() => {
                            this.downloadFile(item.path);
                        }).catch(() => {});
                    }
                },
                
                // 加载文本文件预览
                loadTextPreview(filePath, fileName) {
                    fetch(this.getFileUrl(filePath))    
                        .then(response => {
                            if (!response.ok) {
                                throw new Error(`Network response was not ok: ${response.status}`);
                            }
                            return response.text();
                        })
                        .then(text => {
                            this.previewTextContent = text;
                            this.previewType = 'text';
                            this.previewTitle = fileName;
                            this.previewVisible = true;
                        })
                        .catch(error => {
                            console.error('Error loading file:', error);
                            this.$message.error('加载文件内容失败');
                        });
                },
                
                // 下载文件
                downloadFile(filePath) {
                    window.open(this.getFileUrl(filePath), '_blank');
                },
                
                // 删除文件
                async deleteFile(filePath) {
                    try {
                        const response = await fetch(`/upload/delete?path=${encodeURIComponent(filePath)}`, {
                            method: 'DELETE'
                        });
                        if (!response.ok) {
                            throw new Error(`删除失败: ${response.status}`);
                        }
                        return await response.text();
                    } catch (error) {
                        console.error('删除文件失败:', error);
                        throw error;
                    }
                },
                
                // 删除文件或文件夹
                deleteItem(item) {
                    this.$confirm(`确定要删除${item.directory ? '文件夹' : '文件'} "${item.name}"吗？此操作无法撤销。`, '确认删除', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.loading = true;
                        
                        this.deleteFile(item.path)
                        .then(() => {
                            this.$message.success('删除成功');
                            this.loadFiles(); // 重新加载文件列表
                        })
                        .catch(error => {
                            this.$message.error('删除失败，请稍后重试');
                        })
                        .finally(() => {
                            this.loading = false;
                        });
                    }).catch(() => {
                        // 用户取消删除
                    });
                },
                
                // 显示新建文件夹对话框
                showCreateFolderDialog() {
                    this.folderForm.folderName = '';
                    this.createFolderVisible = true;
                },
                
                // 取消新建文件夹
                cancelCreateFolder() {
                    this.createFolderVisible = false;
                    this.folderForm.folderName = '';
                    this.$refs.folderForm?.resetFields();
                },
                
                // 确认新建文件夹
                confirmCreateFolder() {
                    this.$refs.folderForm.validate(async (valid) => {
                        if (valid) {
                            this.loading = true;
                            try {
                                // 构建完整的文件夹路径
                                const folderName = this.folderForm.folderName.trim();
                                const fullPath = this.currentPath 
                                    ? `${this.currentPath}/${folderName}` 
                                    : folderName;
                                
                                // 调用API创建文件夹
                                const response = await fetch('/upload/folder/create', {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/x-www-form-urlencoded'
                                    },
                                    body: `path=${encodeURIComponent(fullPath)}`
                                });
                                
                                if (!response.ok) {
                                    throw new Error('创建文件夹失败');
                                }
                                
                                const success = await response.json();
                                if (success) {
                                    this.$message.success('文件夹创建成功');
                                    this.createFolderVisible = false;
                                    this.loadFiles(); // 重新加载文件列表
                                } else {
                                    throw new Error('创建文件夹失败');
                                }
                            } catch (error) {
                                console.error('创建文件夹失败:', error);
                                this.$message.error('创建文件夹失败，请稍后重试');
                            } finally {
                                this.loading = false;
                            }
                        }
                    });
                }
            }
        });
    </script>
</body>
</html>